from fastapi import APIRouter, Depends, HTTPException, Request, Query
from fastapi.responses import JSONResponse
from sqlalchemy.orm import Session
import logging
import asyncio
import time
import uuid
import random
from datetime import datetime, timedelta

from app.db.session import get_db
from app.models.models import InternalVideo, InternalJob, InternalUser, InternalVoice
from app.services.external_api_v2 import create_digital_person_v2, create_videomix_v2
from app.services.taskss import TaskManager
from app.utils.validation import Validator
from app.core.config import settings

router = APIRouter()
task_manager = TaskManager()

# 生成随机job_id
def generate_job_id():
    # 生成一个基于UUID的随机字符串，并截取前12位
    random_str = str(uuid.uuid4()).replace('-', '')[:12]
    # 添加时间戳前缀，确保唯一性
    timestamp = int(time.time())
    # 返回格式化的job_id
    return f"INT{timestamp}{random_str}"

# 内部创建数字人接口（无需认证，使用V2外部接口）
@router.post("/internal/video/create")
async def internal_create_digital_human(request: Request, db: Session = Depends(get_db)):
    """
    内部创建数字人接口（无需token验证，使用V2外部接口）
    """
    try:
        data = await request.json()
        video_url = data.get('video_url')
        title = data.get('title')

        if not all([video_url, title]):
            return JSONResponse(status_code=400, content={'error': 'video_url and title are required'})

        # 固定使用内部用户ID
        name_id = "internal_user_123"
        current_time = int(time.time())
        
        # 生成随机video_job_id
        video_job_id = generate_job_id()

        # 检查内部用户是否存在，不存在则创建
        user = db.query(InternalUser).filter(InternalUser.name_id == name_id).first()
        if not user:
            user = InternalUser(name_id=name_id)
            db.add(user)
            db.commit()
            logging.info(f"创建内部用户: {name_id}")

        # 构建V2外部API调用数据
        external_data = {
            'name': title,
            'url': video_url,
            'callback': f"{settings.INTERNAL_VIDEO_CALLBACK_URL}/{video_job_id}"
        }

        logging.info(f"调用V2外部API创建数字人: {external_data}")

        # 调用V2版本的外部 API 创建数字人
        try:
            response_data, status_code = await create_digital_person_v2(external_data)
            logging.info(f"V2外部API响应：状态码={status_code}, 数据={response_data}")
            
            if status_code == 200:
                # 保存到internal_videos表
                new_video = InternalVideo(
                    name_id=name_id,
                    video_url=video_url,  # 先保存原始URL，回调时更新
                    title=title,
                    time=current_time,
                    job_id=video_job_id
                )
                db.add(new_video)
                db.commit()

                logging.info(f"内部数字人创建成功: video_job_id={video_job_id}, title={title}")
                
                return JSONResponse(status_code=200, content={
                    'code': 200,
                    'message': 'Digital human created successfully',
                    'video_job_id': video_job_id
                })
            else:
                logging.error(f"V2外部API调用失败，状态码：{status_code}")
                return JSONResponse(status_code=status_code, content={'error': 'External API error', 'details': response_data})
                
        except Exception as api_error:
            logging.error(f"调用V2外部API时出错：{api_error}")
            return JSONResponse(status_code=500, content={'error': 'External API error'})

    except Exception as e:
        logging.error(f"创建内部数字人时出错: {e}")
        db.rollback()
        return JSONResponse(status_code=500, content={'error': f'Internal server error: {str(e)}'})

# 内部创建任务接口（无需认证，使用V2外部接口）
@router.post("/internal/task/create")
async def internal_create_task(request: Request, db: Session = Depends(get_db)):
    """
    内部创建任务接口（无需token验证，使用V2外部接口进行作品合成）
    """
    try:
        data = await request.json()
        
        # 提取必要参数
        title = data.get('title')
        audio_url = data.get('audio_url')
        video_job_id = data.get('video_job_id')
        
        # 验证必要参数
        if not all([title, audio_url, video_job_id]):
            return JSONResponse(status_code=400, content={'error': 'title, audio_url, and video_job_id are required'})
        
        # 固定使用内部用户ID
        name_id = "internal_user_123"
        
        # 验证video_job_id是否存在，并获取对应的video_url
        video = db.query(InternalVideo).filter(InternalVideo.job_id == video_job_id).first()
        if not video:
            return JSONResponse(status_code=404, content={'error': f'Digital human with video_job_id {video_job_id} not found'})
        
        # 从数据库中获取video_url（这应该是经过V2处理后的数字人视频URL）
        person_url = video.video_url
        logging.info(f"找到数字人视频URL: {person_url} for video_job_id: {video_job_id}")

        # 生成任务job_id
        job_id = int(time.time() * 1000)  # 使用时间戳作为job_id
        
        # 检查内部用户是否存在，不存在则创建
        user = db.query(InternalUser).filter(InternalUser.name_id == name_id).first()
        if not user:
            user = InternalUser(name_id=name_id)
            db.add(user)
            db.commit()

        # 构建V2外部API调用数据（videomix接口）
        # 注意：当使用音频文件时，需要传递voiceUrl而不是content，避免speakerId要求
        external_data = {
            'name': title,
            'personUrl': person_url,  # 数字人视频URL
            'callback': f"{settings.INTERNAL_VIDEOMIX_CALLBACK_URL}/{job_id}",
            'voiceUrl': audio_url,  # 使用voiceUrl参数传递音频文件URL
            'voiceType': 'lite'  # 使用lite声音类型
        }

        logging.info(f"调用V2外部API创建作品: {external_data}")

        # 调用V2版本的外部 API 创建作品
        try:
            response_data, status_code = await create_videomix_v2(external_data)
            logging.info(f"V2外部API响应：状态码={status_code}, 数据={response_data}")
            
            if status_code == 200:
                # 保存到internal_jobs表
                current_timestamp = int(time.time())
                new_job = InternalJob(
                    name_id=name_id,
                    job_id=job_id,
                    video_job_id=video_job_id,  # 关联的数字人job_id
                    title=title,
                    audio_url=audio_url,
                    only_generate_audio=False,  # V2版本生成视频
                    found_time=current_timestamp,
                    status=3,  # 初始状态为处理中
                    message="任务创建成功，正在处理中"
                )
                
                db.add(new_job)
                db.commit()
                
                # V2使用回调机制，无需启动轮询监控
                logging.info(f"内部任务创建成功, job_id={job_id}, linked to video_job_id={video_job_id}，等待V2回调")
                
                return JSONResponse(status_code=200, content={'code': 200, 'job_id': job_id, 'message': '任务已提交，等待处理完成'})
            else:
                logging.error(f"V2外部API调用失败，状态码：{status_code}")
                return JSONResponse(status_code=status_code, content={'error': 'External API error', 'details': response_data})
                
        except Exception as api_error:
            logging.error(f"调用V2外部API时出错：{api_error}")
            return JSONResponse(status_code=500, content={'error': 'External API error'})
            
    except Exception as e:
        logging.error(f"创建内部任务时出错: {e}")
        db.rollback()
        return JSONResponse(status_code=500, content={'error': f'Internal server error: {str(e)}'})

# 内部查询指定任务和数字人接口（无需认证）
@router.get("/internal/task/{job_id}")
async def internal_get_task(job_id: str, db: Session = Depends(get_db)):
    """
    内部查询指定任务接口（支持查询job_id和video_job_id）
    """
    try:
        # 首先尝试作为job_id查找内部任务
        try:
            job_id_int = int(job_id)
            job = db.query(InternalJob).filter(InternalJob.job_id == job_id_int).first()
            
            if job:
                # 如果找到了内部任务，返回任务信息
                video_duration = int(job.video_duration) if job.video_duration is not None else None
                
                result = {
                    'job_id': job.job_id,
                    'video_job_id': job.video_job_id,
                    'video_url': job.video_url if job.video_url else "",
                    'title': job.title,
                    'found_time': job.found_time,
                    'video_duration': video_duration,
                    'status': job.status,
                    'video_time': job.video_time if job.video_time else None
                }
                return JSONResponse(status_code=200, content={'code': 200, 'data': result})
        except ValueError:
            # job_id不是整数，可能是video_job_id格式
            pass
        
        # 如果不是整数或没找到任务，尝试作为video_job_id查找内部数字人
        video = db.query(InternalVideo).filter(InternalVideo.job_id == job_id).first()
        
        if video:
            # 如果找到了内部数字人，返回数字人信息
            result = {
                'video_job_id': video.job_id,
                'video_url': video.video_url if video.video_url else "",
                'title': video.title,
                'found_time': video.time,  # 对于数字人，使用time字段作为found_time
                'type': 'digital_human'  # 标记这是一个数字人记录
            }
            return JSONResponse(status_code=200, content={'code': 200, 'data': result})
        
        # 如果都没找到，返回404
        return JSONResponse(status_code=404, content={'code': 404, 'error': 'Task or digital human not found'})

    except Exception as e:
        logging.error(f"查询内部任务时出错: {e}")
        return JSONResponse(status_code=500, content={'code': 500, 'error': f'Internal server error: {str(e)}'})

# 内部回调接口（用于接收V2外部API的回调）
@router.post("/internal/callback/video/{video_job_id}")
async def internal_video_callback(video_job_id: str, request: Request, db: Session = Depends(get_db)):
    """
    内部数字人创建回调接口
    """
    try:
        data = await request.json()
        logging.info(f"收到数字人创建回调: video_job_id={video_job_id}, data={data}")
        
        # 更新数字人记录
        video = db.query(InternalVideo).filter(InternalVideo.job_id == video_job_id).first()
        if video:
            # 根据回调数据更新video_url等信息
            if 'personUrl' in data:
                video.video_url = data['personUrl']
            db.commit()
            logging.info(f"已更新数字人记录: {video_job_id}")
        
        return JSONResponse(status_code=200, content={'code': 200, 'message': 'Callback received'})
    except Exception as e:
        logging.error(f"处理数字人回调时出错: {e}")
        return JSONResponse(status_code=500, content={'error': 'Internal server error'})

@router.post("/internal/callback/videomix/{job_id}")
async def internal_videomix_callback(job_id: str, request: Request, db: Session = Depends(get_db)):
    """
    内部作品创建回调接口
    """
    try:
        data = await request.json()
        logging.info(f"收到作品创建回调: job_id={job_id}, data={data}")
        
        # 更新任务记录
        job_id_int = int(job_id)
        job = db.query(InternalJob).filter(InternalJob.job_id == job_id_int).first()
        if job:
            # 根据V2回调数据格式更新任务状态
            status = data.get('status')
            url = data.get('url')
            tdata = data.get('tdata', {})
            
            logging.info(f"回调数据解析: job_id={job_id}, status={status}, url={url}, tdata={tdata}")
            
            if status == 'SUCCESS' or status == 'COMPLETED':
                # 任务成功
                logging.info(f"进入成功分支: job_id={job_id}")
                if url:
                    job.video_url = url
                    logging.info(f"设置video_url: {url}")
                job.status = 1  # 完成状态
                job.video_time = int(time.time())
                job.message = "任务完成"
                logging.info(f"任务成功完成: job_id={job_id}, video_url={url}, 新状态={job.status}")
            elif status == 'FAILED' or tdata.get('status') == 4:
                # 任务失败
                logging.info(f"进入失败分支: job_id={job_id}")
                error_message = tdata.get('errorMessage', '任务失败')
                job.status = 4  # 失败状态
                job.message = error_message
                logging.error(f"任务失败: job_id={job_id}, error={error_message}")
            else:
                # 其他状态，记录但不改变状态
                logging.warning(f"未知状态回调: job_id={job_id}, status={status}, tdata={tdata}")
                job.message = f"状态更新: {status}"
            
            db.commit()
            logging.info(f"已更新任务记录: {job_id}, 新状态={job.status}, 消息={job.message}")
        
        return JSONResponse(status_code=200, content={'code': 200, 'message': 'Callback received'})
    except Exception as e:
        logging.error(f"处理作品回调时出错: {e}")
        return JSONResponse(status_code=500, content={'error': 'Internal server error'})